/**
 * 栈
 * 特点：后进先出 LIFO（类似往箱子里放碟好的衣服，取衣服）
 * 
 * add(element)：添加一个或多个新元素到栈顶
 * delete：移除栈顶元素，返回被移除的元素
 * query：返回栈顶元素
 * isEmpty：判断是否为空
 * clear：清空栈
 * size：返回栈里元素的长度
 * 
 * @class Stack
 */
class Stack {
  constructor(){
    this._item = [];
  }

  add(ele){
    this._item.push(ele);
  }
  
  delete(){
    return this._item.pop();
  }

  query(){
    return this._item[this._item.length - 1];
  }

  isEmpty(){
    return this._item.length === 0;
  }

  clear(){
    this._item = [];
  }

  size(){
    return this._item.length;
  }
}

// push 源码
Array.prototype.push = function (...items) {
  let O = Object(this);  // ecma 中提到的先转换为对象
  let len = this.length >>> 0;
  let argCount = items.length >>> 0;
  // 2 ^ 53 - 1 为JS能表示的最大正整数
  if (len + argCount > 2 ** 53 - 1) {
    throw new TypeError("The number of array is over the max value")
  }

  for (let i = 0; i < argCount; i++) {
    O[len + i] = items[i];
  }

  let newLength = len + argCount;
  O.length = newLength;

  return newLength;
}

// pop 源码
Array.prototype.pop = function() {
  let O = Object(this);
  let len = this.length >>> 0;
  if (len === 0) {
    O.length = 0;
    return undefined;
  }

  len--;
  let value = O[len];
  delete O[len];
  O.length = len;

  return value;
}


// 测试
const stack = new Stack();
console.log(stack.isEmpty()); // true

stack.add(5);
stack.add(8);
console.log(stack.query()); // 8

stack.add(11);
console.log(stack.size()); // 3
console.log(stack.isEmpty()); // false

stack.add(15);
stack.delete();
stack.delete();
console.log(stack.size()); // 2

// 进制转换
const baseCouverter = (decNumber, base) => {
  const remStack = new Stack();
  const digits = '0123456789ABCDEFGHIGKLMNOPQRSTUVWXYZ';
  let num = decNumber;
  let rem = 0;
  let baseString = '';

  if(!(base >= 2 && base <= 36)){ return '该进制不是转换区域2～36'; }

  while(num > 0){
    rem = (num % base) | 0;
    remStack.add(rem);
    num = (num / base) | 0;
  }

  while(!remStack.isEmpty()){
    baseString += digits[remStack.delete()];
  }

  return baseString;
}

console.log(baseCouverter(100345, 2));
console.log(baseCouverter(100345, 8));
console.log(baseCouverter(100345, 16));
console.log(baseCouverter(100345, 35));